/***************************************************************************
 *   Copyright (C) 2009 by pawel   *
 *   pawel@byszewski.pl   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef COMMAND_H
#define COMMAND_H

#include <string>
#include "settings.h"
#include "helpers.h"
#include "Exception.h"
/**
	@author pawel <pawel@byszewski.pl>
*/
class Command
{
public:
	int i1,i2;
	float f1,f2;
	std::string s1;
	char type[ELEMENTCOUNT];
	void *list[ELEMENTCOUNT];
	char operation[ELEMENTCOUNT];
    Command(int _i1, int _i2, float _f1, float _f2, std::string _s1){
	    i1=_i1;i2=_i2;f1=_f1;f2=_f2;s1=_s1;
	    type[0]=type[1]=0;
	    type[2]=type[3]=1;
	    type[4]=2;
	    list[0]=(void *)&i1;
	    list[1]=(void *)&i2;
	    list[2]=(void *)&f1;
	    list[3]=(void *)&f2;
	    list[4]=(void *)&s1;

    };
    Command(char a,void * _i1,         char b,void * _i2, 
	      char c, void * _f1,        char d, void * _f2, 
              char e, void * _s1){
	    //i1=_i1;i2=_i2;f1=_f1;f2=_f2;s1=_s1;
	    type[0]=a;type[1]=b;
	    type[2]=c;type[3]=d;
	    type[4]=e;
	    list[0]=_i1;
	    list[1]=_i2;
	    list[2]=_f1;
	    list[3]=_f2;
	    list[4]=_s1;

    };

    Command(char a,void * _i1, char b,void * _i2 ){
	    //i1=_i1;i2=_i2;f1=_f1;f2=_f2;s1=_s1;
	       type[0]=a;type[1]=b;
	       type[2]=9;type[3]=9;
	       type[4]=9;//czyli puste, takie moje arbitralne ustalenie
	       list[0]=_i1;
	       list[1]=_i2;

       };

    Command()
    {

    };


    int decodeType(string op)
    {
    	int ret;
    	if(op == "==")
    		ret = ROWNE;
    	else if(op == "<")
    		ret = MNIEJSZE;
    	else if(op == "<=")
    		ret = MNIEJSZEROWNE;
    	else if(op == ">")
    			ret = WIEKSZE;
    	else if(op == ">=")
    			ret = WIEKSZEROWNE;
    	else if(op == "*")
    			ret= DOWOLNY;
    	else
				ret=-1;
    	return ret;

    }


    void setElement(size_t number, char filedType, void* data)
    {
    	string MOUDLE_NAME("setElement(size_t, char, void*)");
    	type[number] = filedType;
    	list[number] = data;
    	//DEBUG(MOUDLE_NAME, (int)type[number]);
    	//DEBUG(MOUDLE_NAME, *((int*)(list[number])));
    };


    void setElement(size_t number, char filedType, char op, void* data)
    {
    	type[number] = filedType;
    	list[number] = data;
    	operation[number]=op;
    };

    void setElementFromQueryPartOut(const string& queryPart, int where)
    {
    	string MODULE_NAME("setElementFromQueryPart");
    	int k = queryPart.find(":");
		string type = queryPart.substr(0,k);
		string value = queryPart.substr(k+1, queryPart.length());
		if(type == "integer")
		{
			int* datai = new int();
			*datai = atoi(value.c_str());
			this->setElement(where, 0, (void*) datai);
			//DEBUG(MODULE_ID,*datai);
		}

		else if(type == "float")
		{
			float* dataf = new float();
			*dataf = atof(value.c_str());
			this->setElement(where, 1, (void*) dataf);
			//DEBUG(MODULE_ID,*dataf);
		}

		else if(type=="string")
		{
				string* datas = new string(value);
				this->setElement(where, 2, (void*) datas);
				//DEBUG(MODULE_ID,datas);
		}

		else
		{
			DEBUGINFO(MODULE_NAME,"Problem. Nie rozpoznano typu");
			Exception ex;
			ex.setS("Blad, nie rozpoznany typ");
			throw ex;
		}


    }



    void setElementFromQueryPartIn(const string& queryPart, int where)
	{
		string MODULE_NAME("CommandOut.setElementFromQueryPart");
		if(queryPart == "9")
		{
			this->setElement(where, (char)9, DOWOLNY, (void*)0);
		}

		else
		{
			int k = queryPart.find(":");
			string type = queryPart.substr(0,k);
			string value = queryPart.substr(k+1, queryPart.length());


			//Probuje dwa znaki
			int oper = decodeType(value.substr(0,2));
			if(oper < 0)
			{
				//probuje jeden znak
				oper = decodeType(value.substr(0,1));
				if(oper < 0)
				{
					DEBUGINFO(MODULE_NAME,"Blad, zle zdekodowane znak operacji!");
					Exception ex;
					ex.setS("Blad, zle zdekodowane znak operacji!");
					throw ex;
				}
				else
				{
					value = value.substr(1);
				}

			}
			else
			{
				value = value.substr(2);
			}

			//DEBUG(MODULE_NAME,oper);

			//DEBUG(MODULE_NAME, where);
			//DEBUG(MODULE_NAME, oper);
			if(type == "integer")
			{
			    int* datai = new int();
			    *datai = atoi(value.c_str());
			    this->setElement(where, 0,oper, (void*) datai);
				DEBUG(MODULE_NAME,*datai);
			}

			else if(type == "float")
			{
				float* dataf = new float();
				*dataf = atof(value.c_str());
				this->setElement(where, 1, oper,(void*) dataf);
				DEBUG(MODULE_NAME,*dataf);
			}

			else if(type=="string")
			{
				string* datas = new string(value);
				this->setElement(where, 2,oper, (void*) datas);
				DEBUG(MODULE_NAME,datas);
			}

			else
			{
				DEBUGINFO(MODULE_NAME,"Problem. Nie rozpoznano typu operacji");
				Exception ex;
				ex.setS("Blad, nie rozpoznany typ");
				throw ex;
			}
		}

	}



    ~Command()
    {
    	for(int i=0;i<ELEMENTCOUNT;++i ){
    		if(type[i]==0){
    			delete((int*)list[i]);
    		}else if(type[i]==1){
    			delete((float*)list[i]);
    		}else if(type[i]==1){
    			delete((string*)list[i]);
    		}
    	}

    };



};

#endif
